﻿using System;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace PengSW.SqlServerTools
{
    public class ColumnParameter : INotifyPropertyChanged
    {
        #region 构造函数

        public static ColumnParameter IdColumnParameter { get { return new ColumnParameter("Id", ColumnType.IntType, 0, true, true, true); } }

        public ColumnParameter()
        {
            ColumnName = "未命名字段";
            ColumnType = ColumnType.ColumnTypes[0];
            ColumnSize = 255;
            NotNull = false;
            IsPrimaryKey = false;
            IsIdentity = false;
        }

        public ColumnParameter(string aColumnName, ColumnType aColumnType, int aColumnSize = 255, bool aNotNull = false, bool aIsPrimaryKey = false, bool aIsIdentity = false)
        {
            ColumnName = aColumnName;
            ColumnType = aColumnType;
            ColumnSize = aColumnSize;
            NotNull = aNotNull;
            IsPrimaryKey = aIsPrimaryKey;
            IsIdentity = aIsIdentity;
        }

        #endregion

        #region 描述字段的属性

        private string m_ColumnName;
        public string ColumnName { get { return m_ColumnName; } set { SetValue(ref m_ColumnName, value, "ColumnName"); } }

        private ColumnType m_ColumnType;
        public ColumnType ColumnType { get { return m_ColumnType; } set { SetValue(ref m_ColumnType, value, "ColumnType"); } }

        private int m_ColumnSize;
        public int ColumnSize { get { return m_ColumnSize; } set { SetValue(ref m_ColumnSize, value, "ColumnSize"); } }

        private bool m_NotNull;
        public bool NotNull { get { return m_NotNull; } set { SetValue(ref m_NotNull, value, "NotNull"); } }

        private bool m_IsPrimaryKey;
        public bool IsPrimaryKey { get { return m_IsPrimaryKey; } set { SetValue(ref m_IsPrimaryKey, value, "IsPrimaryKey"); } }

        private bool m_IsIdentity;
        public bool IsIdentity { get { return m_IsIdentity; } set { SetValue(ref m_IsIdentity, value, "IsIdentity"); } }

        #endregion

        #region 生成创建字段所需的Sql代码，用于创建表的Sql语句中

        private const string CreateColumnSqlTemplate = @"[{0}] [{1}] {2},"; // Example: [Value] [int] NULL
        private const string CreateColumnSqlTemplateWithSize = @"[{0}] [{1}]({2}) {3},"; // Example: [Value] [nvarchar](255) NOT NULL
        private const string CreateColumnSqlTemplateWithIdentity = @"[{0}] [{1}] IDENTITY(1,1) NOT NULL,"; // Example: [Value] [int] IDENTITY(1,1) NOT NULL

        public string GetCreateColumnSql()
        {
            if (ColumnType.HasSize)
                return string.Format(CreateColumnSqlTemplateWithSize, ColumnName, ColumnType.TypeName, ColumnSize, NotNull ? "NOT NULL" : "NULL");
            else if (ColumnType.CouldBeIdentity && IsIdentity)
                return string.Format(CreateColumnSqlTemplateWithIdentity, ColumnName, ColumnType.TypeName);
            else
                return string.Format(CreateColumnSqlTemplate, ColumnName, ColumnType.TypeName, NotNull ? "NOT NULL" : "NULL");
        }

        #endregion

        #region INotifyPropertyChanged 实现

        private void RaisePropertyChanged(string aPropertyName)
        {
            if (PropertyChanged != null) PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(aPropertyName));
        }

        private void SetValue<T>(ref T aTarget, T aSource, string aPropertyName, params string[] aRelatedPropertyNames)
        {
            if (Object.Equals(aTarget, aSource)) return;
            aTarget = aSource;
            RaisePropertyChanged(aPropertyName);
            if (aRelatedPropertyNames != null) foreach (string aName in aRelatedPropertyNames) RaisePropertyChanged(aName);
        }

        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

        #endregion
    }

    public class ColumnParameters : ObservableCollection<ColumnParameter>
    {
        // TODO: 字段名必须是无重复的
        protected override void InsertItem(int index, ColumnParameter item)
        {
            base.InsertItem(index, item);
        }

        protected override void ClearItems()
        {
            base.ClearItems();
        }

        protected override void RemoveItem(int index)
        {
            base.RemoveItem(index);
        }

        protected override void SetItem(int index, ColumnParameter item)
        {
            base.SetItem(index, item);
        }

        public ColumnType[] ColumnTypes { get { return ColumnType.ColumnTypes; } }
    }
}
